﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MVCQuick.Framework.Repository;

namespace MvcMusicStore.Models
{
    public partial class ShoppingCart
    {
        private IRepository repository;

        public IRepository Repository
        {
            get
            {
                return repository;
            }
            set
            {
                repository = value;
            }
        }

        string ShoppingCartId { get; set; }

        public const string CartSessionKey = "CartId";

        public static ShoppingCart GetCart(IRepository repository, HttpContextBase context)
        {
            var cart = new ShoppingCart();
            cart.repository = repository;
            cart.ShoppingCartId = cart.GetCartId(context);
            return cart;
        }

        // Helper method to simplify shopping cart calls
        public static ShoppingCart GetCart(IRepository repository, Controller controller)
        {
            return GetCart(repository, controller.HttpContext);
        }

        public void AddToCart(Album album)
        {
            // Get the matching cart and album instances 
            var cartItem =
               repository.Query<Cart>()
                   .Where(x => x.Guid == ShoppingCartId)
                   .Where(x => x.Album == album)
                   .SingleOrDefault<Cart>(); 

            if (cartItem == null)
            {
                // Create a new cart item if no cart item exists
                cartItem = new Cart
                {
                    Album = album,
                    Guid = ShoppingCartId,
                    Count = 1,
                    DateCreated = DateTime.Now
                };

                repository.Save<Cart>(cartItem);
            }
            else
            {
                // If the item does exist in the cart, then add one to the quantity
                cartItem.Count++;

                repository.Update<Cart>(cartItem);
            }
           
        }

        public int RemoveFromCart(int id)
        {
            // Get the cart               
            var cartItem =
                repository.Query<Cart>()
                    .Where(x => x.Guid == ShoppingCartId)
                    .Where(x => x.Id == id)
                    .SingleOrDefault<Cart>(); 


            int itemCount = 0;

            if (cartItem != null)
            {
                if (cartItem.Count > 1)
                {
                    cartItem.Count--;
                    itemCount = cartItem.Count;

                    repository.Update<Cart>(cartItem);
                }
                else
                {
                    repository.Delete<Cart>(cartItem);                    
                }               
            }

            return itemCount;
        }

        public void EmptyCart()
        {            
            var cartItems = 
                repository.Query<Cart>()
                    .Where(x => x.Guid == ShoppingCartId)
                    .ToList();               

            foreach (var cartItem in cartItems)
            {
                repository.Delete<Cart>(cartItem);          
            }           
        }

        public List<Cart> GetCartItems()
        {
            return repository.Query<Cart>()
                    .Where(x => x.Guid == ShoppingCartId)
                    .ToList();   
        }

        public int GetCount()
        {
            try
            {
                // Get the count of each item in the cart and sum them up
                int? count =
                    repository.Query<Cart>()
                        .Where(x => x.Guid == ShoppingCartId)
                        .Sum(x => x.Count);

                // Return 0 if all entries are null
                return count ?? 0;
            }
            catch
            {
                return 0;
            }
        }

        public decimal GetTotal()
        {
            try
            {
                // Multiply album price by count of that album to get 
                // the current price for each of those albums in the cart
                // sum all album price totals to get the cart total
                decimal? total =
                    repository.Query<Cart>()
                        .Where(x => x.Guid == ShoppingCartId)
                        .Sum(x => x.Count * x.Album.Price);


                // Get the count of each item in the cart and sum them up           
                return total ?? decimal.Zero;
            }
            catch
            {
                return decimal.Zero;
            }
        }

        public int CreateOrder(Order order)
        {
            decimal orderTotal = 0;

            var cartItems = GetCartItems();

            // Iterate over the items in the cart, adding the order details for each
            foreach (var item in cartItems)
            {
                var orderDetail = new OrderDetail
                {
                    Album = item.Album,
                    Order = order,
                    UnitPrice = item.Album.Price,
                    Quantity = item.Count
                };

                // Set the order total of the shopping cart
                orderTotal += (item.Count * item.Album.Price);

                repository.Save<OrderDetail>(orderDetail);

            }

            // Set the order's total to the orderTotal count
            order.Total = orderTotal;

            // Save the order
            repository.Update(order);

            // Empty the shopping cart
            EmptyCart();

            // Return the OrderId as the confirmation number
            return order.Id;
        }

        // We're using HttpContextBase to allow access to cookies.
        public string GetCartId(HttpContextBase context)
        {
            if (context.Session[CartSessionKey] == null)
            {
                if (!string.IsNullOrWhiteSpace(context.User.Identity.Name))
                {
                    context.Session[CartSessionKey] = context.User.Identity.Name;
                }
                else
                {
                    // Generate a new random GUID using System.Guid class
                    Guid tempCartId = Guid.NewGuid();

                    // Send tempCartId back to client as a cookie
                    context.Session[CartSessionKey] = tempCartId.ToString();
                }
            }

            return context.Session[CartSessionKey].ToString();
        }

        // When a user has logged in, migrate their shopping cart to
        // be associated with their username
        public void MigrateCart(string userName)
        {
            var cartItems =
                repository.Query<Cart>()
                    .Where(x => x.Guid == ShoppingCartId)
                    .ToList(); 

            foreach (Cart item in cartItems)
            {
                item.Guid = userName;

                repository.Update(item);
            }
        }
    }
}